package cn.leizp.springboot.server.netmanger.snmp;

import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;

public class SnmpUtil {
    private static final int PORT = 161;
    private static final int TIMEOUT = 3000;
    private static final int RETRIES = 3;
    private static final OctetString ENGINE_ID = new OctetString(MPv3.createLocalEngineID());

    static {
        // 初始化 USM
        USM usm = new USM(SecurityProtocols.getInstance(), ENGINE_ID, 0);
        SecurityModels.getInstance().addSecurityModel(usm);
    }

    /**
     * 执行 SNMPv3 GET 请求
     * 
     * @param ip           设备 IP 地址
     * @param oid          OID
     * @param securityName 安全名称
     * @param authProtocol 认证协议
     * @param authPassword 认证密码
     * @param privProtocol 加密协议
     * @param privPassword 加密密码
     * @return 返回值
     */
    public static String snmpGetV3(String ip, String oid, String securityName, OID authProtocol, String authPassword,
            OID privProtocol, String privPassword) {
        try {
            // 创建 TransportMapping 并监听
            TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
            transport.listen();

            // 创建 SNMP 实例
            Snmp snmp = new Snmp(transport);

            // 创建安全用户
            UsmUser user = new UsmUser(new OctetString(securityName), authProtocol,
                    new OctetString(authPassword), privProtocol, new OctetString(privPassword));
            snmp.getUSM().addUser(new OctetString(securityName), user);

            // 创建目标对象
            UserTarget target = new UserTarget();
            target.setAddress(new UdpAddress(ip + "/" + PORT));
            target.setRetries(RETRIES);
            target.setTimeout(TIMEOUT);
            target.setVersion(SnmpConstants.version3);
            target.setSecurityLevel(org.snmp4j.security.SecurityLevel.AUTH_PRIV);
            target.setSecurityName(new OctetString(securityName));

            // 创建 PDU
            ScopedPDU pdu = new ScopedPDU();
            pdu.add(new VariableBinding(new OID(oid)));
            pdu.setType(PDU.GET);

            // 发送请求
            ResponseEvent event = snmp.send(pdu, target);
            if (event != null) {
                if (event.getError() != null) {
                    System.out.println(oid + " 响应: " + event.getError().getMessage());
                }
                PDU response = event.getResponse();
                if (response != null) {
                    VariableBinding vb = response.getVariableBindings().get(0);
                    if (vb != null) {
                        return vb.getVariable().toString();
                    }
                }
            }

            // 关闭连接
            snmp.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 执行 SNMPv3 SET 请求
     * 
     * @param ip           设备 IP 地址
     * @param oid          OID
     * @param value        要设置的值
     * @param securityName 安全名称
     * @param authProtocol 认证协议
     * @param authPassword 认证密码
     * @param privProtocol 加密协议
     * @param privPassword 加密密码
     * @return 设置结果
     */
    public static boolean snmpSetV3(String ip, String oid, String value, String securityName, OID authProtocol,
            String authPassword, OID privProtocol, String privPassword) {
        try {
            // 创建 TransportMapping 并监听
            TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
            transport.listen();

            // 创建 SNMP 实例
            Snmp snmp = new Snmp(transport);

            // 创建安全用户
            UsmUser user = new UsmUser(new OctetString(securityName), authProtocol,
                    new OctetString(authPassword), privProtocol, new OctetString(privPassword));
            snmp.getUSM().addUser(new OctetString(securityName), user);

            // 创建目标对象
            UserTarget target = new UserTarget();
            target.setAddress(new UdpAddress(ip + "/" + PORT));
            target.setRetries(RETRIES);
            target.setTimeout(TIMEOUT);
            target.setVersion(SnmpConstants.version3);
            target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
            target.setSecurityName(new OctetString(securityName));

            // 创建 PDU
            ScopedPDU pdu = new ScopedPDU();
            pdu.add(new VariableBinding(new OID(oid), new OctetString(value)));
            pdu.setType(PDU.SET);

            // 发送请求
            ResponseEvent event = snmp.send(pdu, target);
            if (event != null) {
                PDU response = event.getResponse();
                if (response != null && response.getErrorStatus() == PDU.noError) {
                    snmp.close();
                    return true;
                }
            }
            snmp.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) {
        String ip = "192.168.55.1";
        String oid = "1.3.6.1.2.1.1.1.0";
        String securityName = "admin";
        OID authProtocol = AuthMD5.ID;
        String authPassword = "1qaz2wsx3edc";
        OID privProtocol = PrivDES.ID;
        String privPassword = "1qaz@WSX";
        // String value = "New System Description";

        // 执行 SNMPv3 GET 请求
        String getResult = snmpGetV3(ip, oid, securityName, authProtocol, authPassword, privProtocol, privPassword);
        if (getResult != null) {
            System.out.println(oid + " GET 响应: " + getResult);
        }

        // 执行 SNMPv3 SET 请求
        // boolean setResult = snmpSetV3(ip, oid, value, securityName, authProtocol,
        // authPassword, privProtocol, privPassword);
        // System.out.println(oid + " SET 结果: " + setResult);
    }
}
